package net.xuele.learn.queue;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;

public class StatefulConcurrentLinkedQueue<T> extends ConcurrentLinkedQueue<T> {
    private static final long serialVersionUID = 7520889528851063995L;

    private Integer size;

    private float threshold;


    private AtomicLong cap = new AtomicLong(0L);


    public StatefulConcurrentLinkedQueue(int size, float loadFactor) {
        super();
        this.size = size;
        threshold = (int) size * loadFactor;
    }

    /**
     * 默认是可用的
     */
    private boolean available = true;

    public void disable() {
        this.available = false;
    }

    public void enable() {
        this.available = true;
    }


    /**
     * 说明队列满了，因为多线程竞争的情况下，也会一直尝试往里面塞数据，队列的长度是通过外界辅助的方式控制的
     * 可能存在队列长度大于我们设置大小的情况
     * @param t
     * @return
     */
    @Override
    public boolean offer(T t) {
        if (cap.get() >= size) {
            return false;
        }
        // 最终一定会成功，所以一定会返回true
        boolean offer = super.offer(t);
        if (offer) {
            cap.incrementAndGet();
        }
        return offer;
    }

    @Override
    public T poll() {
        T poll = super.poll();
        if (poll != null) {
            cap.decrementAndGet();
        }
        return poll;
    }


    public boolean canUse() {
        return available && threshold > cap.get();
    }
}
